#include "utils.h"

#ifndef GIFDECODER_H
#define GIFDECODER_H

using namespace std;

/**
 * \class GIFFile
 *
 * \brief Read and decode GIF files (standard 87a) . 
 *
 * \author Maksym Rybak
 * \date 17.03.2011
**/
class GIFFile{	

	/**
	 * \struct GIFSignature
	 *
	 * \brief Identifies the data following as a valid GIF image stream.
	 *
	 * \author Maksym Rybak
	 * \date 17.03.2011
	**/
	struct GIFSignature{
		int signatureSize;					///< Signature size in byte (by default is 6 Bytes)
		string signature;					///< Signature string (GIF87a / GIF89a)		

		GIFSignature();
		bool readGIFSignature(istream &in);
		void printGIFSignature();
	};	
	GIFSignature _GIFSignature;				///< The gif signature

	/**
	 * \struct ScreenDescriptor
	 *
	 * \brief Describes the overall parameters for all GIF images following. 
	 *
	 * \author Maksym Rybak
	 * \date 17.03.2011
	**/
	struct ScreenDescriptor{
		WORD Width;						///< Raster width in pixels (LSB first)
		WORD Height;					///< Raster height in pixels (LSB first)
		short int M;					///< If M = 1 Global color map follows Descriptor
		short int cr;					///< cr+1 = # bits of color resolution
		short int pixel;				///< pixel+1 = # bits/pixel in image (defines  the  maximum  number  of  colors within  an  image)
		BYTE background;				///< background = Color index of screen background
		BYTE AspectRatio;				///< 0 Byte

		bool readScreenDescriptor(istream &in);
		void printScreenDescriptor();
	};
	ScreenDescriptor _ScreenDescriptor; ///< The screen descriptor

	/**
	 * \struct ColorMapEntry
	 *
	 * \brief Represent single entry in Global/Local Color Map. 
	 *
	 * \author Maksym Rybak
	 * \date 17.03.2011
	**/
	struct ColorMapEntry{						
		BYTE rgbRed;					///< Red intensity 
		BYTE rgbGreen;					///< Green intensity 
		BYTE rgbBlue;					///< Blue intensity 

		bool getColorMapEntry(istream &in);
	};

	/**
	 * \struct GlobalColorMap
	 *
	 * \brief Used to index the pixel color data contained within the image data. 
	 *
	 * \author Maksym Rybak
	 * \date 17.03.2011
	**/
	struct GlobalColorMap{
		int bitPerPixel;				///< Pixel size in bit
		ColorMapEntry *_ColorMap;		///< The buffer to memorize Global Color Map

		GlobalColorMap();
		~GlobalColorMap();
		bool readGlobalColorMap(istream &in);
		bool buildDefaultGlobalColorMap();
		void printGlobalColorMap();
	};
	GlobalColorMap _GlobalColorMap;		///< The global color map

	/**
	 * \struct LocalImageDescriptor
	 *
	 * \brief Defines the actual placement and extents of the image. 
	 *
	 * \author Maksym Rybak
	 * \date 17.03.2011
	**/
	struct LocalImageDescriptor{
		WORD ImageLeft;					///< Start of image in pixels from the left side of the screen (LSB first)
		WORD ImageTop;					///< Start of image in pixels from the top of the screen (LSB first)
		WORD ImageWidth;				///< Width of the image in pixels (LSB first)
		WORD ImageHeight;				///< Height of the image in pixels (LSB first)
		short int M;					///< M=0 - Use global color map, ignore 'pixel'
										///< M=1 - Local color map follows, use 'pixel'
		short int I;					///< I=0 - Image formatted in Sequential order
										///< I=1 - Image formatted in Interlaced order
		short int pixel;				///< pixel+1 - # bits per pixel for this image
		
		bool readLocalImageDescriptor(istream &in);
		void printLocalImageDescriptor();
	};
	LocalImageDescriptor _LocalImageDescriptor; ///< The local image descriptor

	/**
	 * \struct LocalColorMap
	 *
	 * \brief Used to index the pixel color data contained within the local image data.
	 * 		  Is optional, if not present we use Global Color Map. 
	 *
	 * \author Maksym Rybak
	 * \date 17.03.2011
	**/
	struct LocalColorMap{
		int bitPerPixel;				///< Pixel size in bit
		ColorMapEntry *_ColorMap;		///< The buffer to memorize Global Color Map

		LocalColorMap();
		~LocalColorMap();
		bool readLocalColorMap(istream &in);		
	};
	LocalColorMap _LocalColorMap;		///< The local color map

	/**
	 * \struct RasterData
	 *
	 * \brief Series of pixel color index values that make up the image. 
	 *
	 * \author Maksym Rybak
	 * \date 17.03.2011
	**/
	struct RasterData{
		BYTE CodeSize;					///< Number of bits needed to represent the actual data

		bool readRasterData(istream &in, BYTE *ImageIndices);
		bool Interlaced2Sequential(BYTE *ImageIndices, int ImageWidth, int ImageHeight);		
	};
	RasterData _RasterData;				///< Information describing the raster

	BYTE *ImageIndices;					///< The buffer where we'll put decoded Image Indices
	ColorPaletteEntry *ColorPalette;	///< Color Palette

public:
	GIFFile();
	~GIFFile();

	bool readGIFFile(istream &in);
	void printGIFFile();

	WORD getImageWidth();
	WORD getImageHeight();	
	BYTE *getImageIndices();
	ColorPaletteEntry *getColorMap();
};

#endif /* GIFDECODER */